﻿///////////////////////////////////////////////////////////////////////////////
// File Name: SkinWnd.cpp 
// Purpose: SkinWnd.h 实现文件
// Author: 张东斌、ChongyangLee, lynnux
// E_Mail: malutianshi7905@sina.com; ChongyangLee@hotmail.com
// History: 
// 2009/10/15 Add GetBorderAndScroll()
// 2010/1/12  Mod ConvertMenu添加对系统菜单的处理,改m_bHasMenu默认为TRUE by lynnux
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "skinwnd.h"
#include "PopupMenuSkin.h"

#define safe_delete(p){if(p){delete p;p=NULL;}}
// constants used for drawing
const int CXGAP = 0;				// num pixels between button and text
const int CXTEXTMARGIN = 0;		// num pixels after hilite to start text
const int CXBUTTONMARGIN = 0;	// num pixels wider button is than bitmap
const int CYBUTTONMARGIN = 0;	// ditto for height


// identifies owner-draw data as mine
const LONG MYITEMID = MAKELONG(MAKEWORD(_T('m'),_T('i')),MAKEWORD(_T('d'),_T('0')));

// private struct: one of these for each owner-draw menu item
struct CMyItemData {
	long		magicNum;		// magic number identifying me
	CString		text;				// item text
	UINT		fType;			// original item type flags
	CMyItemData()				{ magicNum = MYITEMID; }
	~CMyItemData()				{ text.Empty(); }
	BOOL IsMyItemData()		{ return magicNum == MYITEMID; }
};
/******************************************
* 函数名 : CSkinWnd
* 功能	 : 构造函数 
*******************************************/
CSkinWnd::CSkinWnd(void)
: m_bEnableSkin(TRUE)
, m_bTrans(FALSE)
{
	m_bHasMenu = TRUE; //lynnux 
	m_hScrollTracking = 0;
	m_nTrackingBar = 0;
	m_nTrackingPos = 0;
	m_nTrackingVal = 0;
	m_pSkinScrollBar = GetSkin().GetScrollBarSkin();
	m_pPopupMenu = GetSkin().GetPopupMenuSkin();
	m_colorTrans = GetSkin().m_Application.colorTransparent;

	m_nHArrowLeftState = keScrollNormal;
	m_nHArrowRightState =  keScrollNormal;
	m_nHThumbState = keScrollNormal;

	m_nVArrowTopState = keScrollNormal;
	m_nVArrowBottomState = keScrollNormal;
	m_nVThumbState = keScrollNormal;

	m_nTrackingBar = FALSE;

	m_rtHScroll= CRect(0,0,0,0);
	m_rtVScroll = CRect(0,0,0,0);
	m_nHScrollPos = 0;
	m_nVScrollPos = 0;
	SB_InitializeApp();
	m_pScrollWnd = NULL;
}
/******************************************
* 函数名 : ~CSkinWnd
* 功能	 : 析构函数 
*******************************************/
CSkinWnd::~CSkinWnd(void)
{
	SB_UninitializeApp();
}
BOOL CSkinWnd::InstallSkin(HWND hWnd)
{
    return FALSE;
}
BOOL CSkinWnd::InstallSkin(HWND hWnd,const CString& strSkinName)
{
    return FALSE;
}
BOOL CSkinWnd::LoadSkin()
{
    HookWindow((HWND)NULL);
    return FALSE;
}
/******************************************
* 函数名 : WindowProc
* 功能	 : 消息处理函数,在此进行处理需要处理的消息 
*******************************************/
LRESULT CSkinWnd::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
{
	//当前窗口不存在返回
	if ( !IsWindow(m_hWnd) )
		return 0;
	//默认消息处理,不进行换肤
	if(!m_bEnableSkin)
		return Default();
	return OnWndMsg(msg, wp, lp);
}
/******************************************
* 函数名 : OnWndMsg
* 功能	 : 处理相应窗口消息
*******************************************/
LRESULT CSkinWnd::OnWndMsg(UINT msg, WPARAM wp, LPARAM lp)
{
	switch ( msg )
	{
	//下面非客户区消息处理
	case WM_NCPAINT:
		OnNcPaint( (HRGN)wp );
		return 0;
	case WM_NCCALCSIZE:
		OnNcCalcSize( (BOOL)wp, (NCCALCSIZE_PARAMS *)lp );
		return 0;
	case WM_NCACTIVATE:
		return OnNcActivate( (BOOL)wp );
	case WM_NCHITTEST:
		return OnNcHitTest(CPoint(LOWORD(lp), HIWORD(lp)));
	case WM_NCLBUTTONUP:
		OnNcLButtonUp((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_NCLBUTTONDOWN:
		OnNcLButtonDown((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_NCLBUTTONDBLCLK:
		OnNcLButtonDblClk((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_NCRBUTTONUP:
		OnNcRButtonUp((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_NCRBUTTONDOWN:
		OnNcRButtonDown((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_NCRBUTTONDBLCLK:
		OnNcRButtonDblClk((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_NCMOUSEMOVE:
		OnNcMouseMove( (UINT)wp,CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_SHOWWINDOW:
		OnShowWindow((BOOL)wp,(UINT)lp);
		return 0;
	case WM_PAINT:
		OnPaint();
		return 0;
	case WM_SIZE:
		OnSize((UINT)wp,LOWORD(lp),HIWORD(lp));
		return 0;
	case WM_SIZING:
		OnSizing((UINT)wp,(LPRECT)lp);
		return 0;
	case WM_ERASEBKGND:
		OnEraseBkgnd(CDC::FromHandle(reinterpret_cast<HDC>(wp)));
		return 0;
	case WM_ACTIVATE:
		OnActivate((UINT)wp, (HWND)lp, 0 );
		return 0;
	case WM_SETCURSOR:
		return OnSetCursor((HWND)wp,LOWORD(lp), HIWORD(lp));
	case WM_LBUTTONUP:
		OnLButtonUp((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_LBUTTONDOWN:
		OnLButtonDown((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_MOUSEMOVE:
		OnMouseMove( (UINT)wp,CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_LBUTTONDBLCLK:
		OnLButtonDblClk((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp)));
		return 0;
	case WM_GETMINMAXINFO:
		OnGetMinMaxInfo((LPMINMAXINFO)lp);
		return 0;
	case WM_DRAWITEM:
		return OnDrawItem((int)wp,(LPDRAWITEMSTRUCT)lp);
	case WM_MEASUREITEM:
		OnMeasureItem((LPMEASUREITEMSTRUCT)lp);
		return 0;
	case WM_SYSCOMMAND:
		OnSysCommand((UINT)wp,lp);
		return 0;
	case WM_TIMER:
		OnTimter((UINT_PTR)wp);
		return 0;
	case WM_HSCROLL:
		OnHScroll(wp,lp);
		return 0;
	case WM_SETFOCUS:
		OnSetFocus((HWND)wp);
		return 0;
	case WM_KILLFOCUS:
		OnKillFocus((HWND)wp);
		return 0;
	case WM_ENABLE:
		OnEnable((BOOL)wp);
		return 0;
	case WM_SETTEXT:
		OnSetText(wp,lp);
		return 0;
	case WM_SETICON:
		return OnSetIcon((UINT)wp,(HICON)lp);
	case WM_INITMENUPOPUP:
		OnInitMenuPopup(CMenu::FromHandle((HMENU)wp),
			(UINT)LOWORD(lp), (BOOL)HIWORD(lp));
		return 0;
	case WM_MENUSELECT:
		OnMenuSelect((UINT)LOWORD(wp), (UINT)HIWORD(wp), (HMENU)lp);
		return 0;
	case WM_MENUCHAR:
		return OnMenuChar((TCHAR)LOWORD(wp), (UINT)HIWORD(wp),
				CMenu::FromHandle((HMENU)lp));
		
	case WM_CAPTURECHANGED:
		OnCaptureChanged(wp,lp);
		return 0;

	case WM_DESTROY:
		OnDestroy();
		return 0;
	
		//消息处理
	default:
		return Default();
	}
	return 0;
}
/******************************************
* 函数名 : OnDestroy
* 功能	 :  
*******************************************/
void CSkinWnd::OnDestroy()
{
	Default();
}
/******************************************
* 函数名 : OnCaptureChanged
* 功能	 :  
*******************************************/
void CSkinWnd::OnCaptureChanged(WPARAM wp,LPARAM lp)
{
	Default();
}
/******************************************
* 函数名 : OnInitMenuPopup
* 功能	 :  
*******************************************/
void CSkinWnd::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
{
	//if(m_bHasMenu)
	//	ConvertMenu(pMenu, nIndex, bSysMenu, TRUE);
	//else
		Default();
}
/******************************************
* 函数名 : OnMenuChar
* 功能	 :  
*******************************************/
LRESULT CSkinWnd::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu)
{
    return Default();
	//if(m_bHasMenu)
	//{
	//	ASSERT_VALID(pMenu);

	//	UINT iCurrentItem = (UINT)-1; 
	//	CUIntArray arItemsMatched;
	//	UINT nItem = pMenu->GetMenuItemCount();
	//	for (UINT i=0; i< nItem; i++) {
	//		CMenuItemInfo info;
	//		info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
	//		::GetMenuItemInfo(*pMenu, i, TRUE, (MENUITEMINFO *)&info);

	//		CMyItemData* pmd = (CMyItemData*)info.dwItemData;
	//		if ((info.fType & MFT_OWNERDRAW) && pmd && pmd->IsMyItemData()) {
	//			CString& text = pmd->text;
	//			int iAmpersand = text.Find(_T('&'));
	//			if (iAmpersand >=0 && toupper(nChar)==toupper(text[iAmpersand+1]))
	//				arItemsMatched.Add(i);
	//		}
	//		if (info.fState & MFS_HILITE)
	//			iCurrentItem = i; // note index of current item
	//	}

	//	UINT nFound = (UINT)arItemsMatched.GetSize();
	//	if (nFound == 0)
	//		return 0;

	//	else if (nFound==1)
	//		return MAKELONG(arItemsMatched[0], MNC_EXECUTE);

	//	// more than one found--return 1st one past current selected item;
	//	UINT iSelect = 0;
	//	for (unsigned int j=0; j < nFound; ++j) {
	//		if (arItemsMatched[j] > iCurrentItem) {
	//			iSelect = j;
	//			break;
	//		}
	//	}
	//	return MAKELONG(arItemsMatched[iSelect], MNC_SELECT);
	//}
	//else
	//	return Default();
}
/******************************************
* 函数名 : OnMenuSelect
* 功能	 :  
*******************************************/
void CSkinWnd::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
    Default();
	//if(m_bHasMenu)
	//{
	//	if (hSysMenu==NULL && nFlags==0xFFFF) {
	//		// Windows has closed the menu: restore all menus to original state
	//		while (!m_menuList.IsEmpty()) {
	//			ConvertMenu(CMenu::FromHandle((HMENU)m_menuList.RemoveHead()),
	//				0, FALSE, FALSE);
	//		}
	//	}
	//}
	//Default();
}
/******************************************
* 函数名 : OnSetIcon
* 功能	 : 设置窗口的图标 
*******************************************/
LRESULT CSkinWnd::OnSetIcon(UINT nFlag,HICON hIcon)
{
	return Default();
}
/******************************************
* 函数名 : OnEnable
* 功能	 : 窗口状态发生变化时调用 
*******************************************/
void CSkinWnd::OnSetText(WPARAM wp,LPARAM lp)
{
	Default();
}
/******************************************
* 函数名 : OnEnable
* 功能	 : 窗口状态发生变化时调用 
*******************************************/
void CSkinWnd::OnEnable(BOOL bEnable)
{
	Default();
}
/******************************************
* 函数名 : OnNcRButtonUp
* 功能	 : 非客户区用户放开鼠标右键调用 
*******************************************/
void CSkinWnd::OnNcRButtonUp( UINT nHitTest, const CPoint& point )
{
	 Default();
}
/******************************************
* 函数名 : OnNcRButtonDown
* 功能	 : 非客户区用户按下鼠标右键调用 
*******************************************/
void CSkinWnd::OnNcRButtonDown( UINT nHitTest, CPoint point )
{
	 Default();
}
/******************************************
* 函数名 : OnNcRButtonDblClk
* 功能	 : 非客户区用户双击鼠标右键调用 
*******************************************/
void CSkinWnd::OnNcRButtonDblClk( UINT nHitTest, const CPoint& point )
{
	 Default();
}
/******************************************
* 函数名 : OnNcMouseMove
* 功能	 : 非客户区鼠标移动 
*******************************************/
void CSkinWnd::OnNcMouseMove( UINT nHitTest, const CPoint& point )
{

	Default();
}
/******************************************
* 函数名 : OnNcLButtonUp
* 功能	 : 非客户区放开鼠标左键 
*******************************************/
void CSkinWnd::OnNcLButtonUp( UINT nHitTest, const CPoint& point )
{
	Default();
}
/******************************************
* 函数名 : OnNcLButtonDown
* 功能	 : 非客户区按下鼠标左键 
*******************************************/
void CSkinWnd::OnNcLButtonDown( UINT nHitTest, const CPoint& point )
{
	Default();
	 
}
/******************************************
* 函数名 : OnNcLButtonDblClk
* 功能	 : 非客户区双击鼠标左键 
*******************************************/
void CSkinWnd::OnNcLButtonDblClk( UINT nHitTest, const CPoint& point )
{
	Default();
}
/******************************************
* 函数名 : OnNcHitTest
* 功能	 : 当鼠标移动时调用此函数 
*******************************************/
UINT CSkinWnd::OnNcHitTest( const CPoint& point )
{
	return (UINT)Default();
}
/******************************************
* 函数名 : OnNcActivate
* 功能	 : 改变非客户区活动或非活动状态调用 
*******************************************/
BOOL CSkinWnd::OnNcActivate( BOOL bActive )
{
	return (BOOL)Default();
}
/******************************************
* 函数名 : OnNcCalcSize
* 功能	 : 当计算客户区大小和位置时调用 
*******************************************/
void CSkinWnd::OnNcCalcSize( BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
	 Default();
}

///////////////////////////////////////////////////////////////////////////////
// 
///////////////////////////////////////////////////////////////////////////////
void CSkinWnd::OnNcCalcSizeSB(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *lpncsp)
{
#ifdef _WIN64
	LONG_PTR style = GetWindowLongPtr(m_hWnd, GWL_STYLE);
#else
	DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
#endif
	SCROLLBAR *sb = NULL;

	m_bHScroll		= style & WS_HSCROLL;
	m_bVScroll		= style & WS_VSCROLL;

	LPRECT lpRect = &(lpncsp->rgrc[0]);
	if(m_bBorder)
	{
		lpncsp->rgrc[0].left += 1;
		lpncsp->rgrc[0].top += 1;
		lpncsp->rgrc[0].right -= 1;
		lpncsp->rgrc[0].bottom -= 1;

		lpncsp->rgrc[1] = lpncsp->rgrc[0];
	}

	if(m_bHScroll)
	{
		sb = GetScrollBarFromHwnd(m_hWnd, SB_HORZ);

		if(sb != NULL)
		{
			if(sb->fScrollFlags & CSBS_VISIBLE)
			{
				if( lpRect->bottom - lpRect->top > GetSystemMetrics(SM_CYHSCROLL))
					lpRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
				sb->fScrollVisible = TRUE;
			}
			else
			{
				sb->fScrollVisible = FALSE;
			}
		}
	}


	if(m_bVScroll)
	{
		sb = GetScrollBarFromHwnd(m_hWnd, SB_VERT);

		if(sb != NULL)
		{
			if(sb->fScrollFlags & CSBS_VISIBLE)
			{
				if( lpRect->right - lpRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
					if(m_bLeftScroll)
						lpRect->left  += GetSystemMetrics(SM_CXVSCROLL);
					else
						lpRect->right -= GetSystemMetrics(SM_CXVSCROLL);
				}
				sb->fScrollVisible = TRUE;
			}
			else
			{
				sb->fScrollVisible = FALSE;
			}
		}
	}


}

/******************************************
* 函数名 : OnNcPaint
* 功能	 : 当非客户需要重画时调用 
*******************************************/
void CSkinWnd::OnNcPaint(HRGN rgn1)
{
	Default();
}
/******************************************
* 函数名 : OnShowWindow
* 功能	 : 当窗口被隐藏或显示调用 
*******************************************/
void CSkinWnd::OnShowWindow( BOOL bShow, UINT nStatus)
{
	 Default();
}
/******************************************
* 函数名 : OnPaint
* 功能	 : 当客户需要重画时调用
*******************************************/
void CSkinWnd::OnPaint()
{
	 Default();
}
/******************************************
* 函数名 : OnSize
* 功能	 : 当窗口的大小被改变后调用 
*******************************************/
void CSkinWnd::OnSize(UINT nType, int cx, int cy )
{
	 Default();
}
/******************************************
* 函数名 : OnSizing
* 功能	 : 用户正在改变窗口的大小 
*******************************************/
BOOL CSkinWnd::OnSizing(UINT fwSide, LPRECT pRect)
{
	return (BOOL)Default();
}
/******************************************
* 函数名 : OnEraseBkgnd
* 功能	 : 查除窗口的背景调用 
*******************************************/
BOOL CSkinWnd::OnEraseBkgnd(CDC* pDC)
{
	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
	CRect rtClient;
	pWnd->GetClientRect( rtClient );
	
	return (BOOL)Default();
}
/******************************************
* 函数名 : OnSetCursor
* 功能	 : 光标在窗口移动时调用 
*******************************************/
BOOL CSkinWnd::OnSetCursor(HWND hWnd, UINT nHitTest, UINT message)
{
	return (BOOL)Default();
}
/******************************************
* 函数名 : OnSetFocus
* 功能	 : 窗口获得输入焦点时调用 
*******************************************/
void CSkinWnd::OnSetFocus(HWND hWnd)
{
	 Default();
}
/******************************************
* 函数名 : OnSetFocus
* 功能	 : 窗口失去输入焦点时调用 
*******************************************/
void CSkinWnd::OnKillFocus(HWND hWnd)
{
	Default();
}
/******************************************
* 函数名 : OnActivateApp
* 功能	 : 应用程序被激活或退出激活状态时调用 
*******************************************/
void CSkinWnd::OnActivateApp(BOOL bActive, HTASK hTask)
{
	 Default();
}
/******************************************
* 函数名 : OnNcPaint
* 功能	 : 当需要知道最大化的位置和大小,或最小或最大跟踪尺寸时调用 
*******************************************/
void CSkinWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
	 Default();
}
/******************************************
* 函数名 : OnMouseMove
* 功能	 : 鼠标移动时调用 
*******************************************/
void CSkinWnd::OnMouseMove( UINT nFlags, const CPoint& point )
{
	 Default();
}
/******************************************
* 函数名 : OnLButtonDown
* 功能	 : 鼠标左键按下时调用 
*******************************************/
void CSkinWnd::OnLButtonDown( UINT nFlags, const CPoint& point )
{
	 Default();
}
/******************************************
* 函数名 : OnLButtonUp
* 功能	 : 鼠标左键放开时调用 
*******************************************/
void CSkinWnd::OnLButtonUp( UINT nFlags, const CPoint& point )
{
	Default();
}
/******************************************
* 函数名 : OnLButtonDblClk
* 功能	 : 鼠标左键双击时调用 
*******************************************/
void CSkinWnd::OnLButtonDblClk( UINT nFlags, const CPoint& point )
{
	Default();
	
}
/******************************************
* 函数名 : OnVScroll
* 功能	 : 用户单击窗口垂直滚动条调用 
*******************************************/
void CSkinWnd::OnVScroll(WPARAM wParam, LPARAM lParam)
{
	Default();
}
/******************************************
* 函数名 : OnHScroll
* 功能	 : 用户单击窗口水平滚动条调用 
*******************************************/
void CSkinWnd::OnHScroll(WPARAM wParam, LPARAM lParam)
{
	Default();
}
/******************************************
* 函数名 : OnNotify
* 功能	 :  
*******************************************/
LRESULT CSkinWnd::OnNotify(WPARAM wParam, LPARAM lParam)
{

	return Default();
}
/******************************************
* 函数名 : OnNotify
* 功能	 :  
*******************************************/
void CSkinWnd::OnNotify(UINT uNotify, UINT uID, CWnd* pCtrl)
{
	 Default();
}
/******************************************
* 函数名 : OnNotifyReflect
* 功能	 :  
*******************************************/
LRESULT CSkinWnd::OnNotifyReflect(NMHDR* pNMHDR, LRESULT lrParent)
{
	return Default();
}
/******************************************
* 函数名 : OnNotifyReflect
* 功能	 :  
*******************************************/
void CSkinWnd::OnNotifyReflect(UINT uNotify, LRESULT lrParent)
{
	 Default();
}
/******************************************
* 函数名 : OnStyleChanged
* 功能	 :  
*******************************************/
void CSkinWnd::OnStyleChanged(int nStyleType,LPSTYLESTRUCT lpStyleStruct)
{
	 Default();
}
/******************************************
* 函数名 : OnSysCommand
* 功能	 :  
*******************************************/

void CSkinWnd::OnSysCommand(UINT nID, LPARAM lParam )
{
	 Default();
}
/******************************************
* 函数名 : OnDrawItem
* 功能	 :  
*******************************************/
BOOL CSkinWnd::OnDrawItem(int nIDCtrl,LPDRAWITEMSTRUCT lpds)
{
    return (BOOL)Default();
	//if(m_bHasMenu && (lpds->CtlType == ODT_MENU))
	//{
	//	CMenuItemInfo info;
	//	CRect rcText;
	//	CMyItemData* pmd = (CMyItemData*)lpds->itemData;
	//	ASSERT(pmd);
	//	if (!pmd->IsMyItemData())
	//		return FALSE;
	//	ASSERT(lpds->itemAction != ODA_FOCUS);
	//	ASSERT(lpds->hDC);
	//	CDC dc;
	//	dc.Attach(lpds->hDC);

	//	const CRect& rcItem = lpds->rcItem;
	//	if (pmd->fType & MFT_SEPARATOR)
	//	{
	//		// draw separator
	//		CRect rc = rcItem;	
	//		DrawSeparator(rc,dc);

	//	} 
	//	else
	//	{													// not a separator

	//		BOOL bDisabled = lpds->itemState & ODS_GRAYED;
	//		BOOL bSelected = lpds->itemState & ODS_SELECTED;
	//		BOOL bChecked  = lpds->itemState & ODS_CHECKED;
	//		BOOL bHaveButn=FALSE;
	//		int cxButn = 0;				// width of button
	//		//COLORREF colorBG = bSelected ? GuiDrawLayer::GetRGBFondoXP(): GetSysColor(WHITE_PEN) ;
	//		CRect rcBG = rcItem;

	//		if (bSelected || lpds->itemAction==ODA_SELECT)
	//		{

	//			if (bSelected && !bDisabled)
	//				PLSelectRect(dc, rcBG);
	//			else
	//				PLNormalRect(dc, rcBG);

	//		}
	//		else
	//			PLNormalRect(dc, rcBG);

	//		// compute text rectangle and colors
	//		rcText = rcItem;				 // start w/whole item
	//		rcText.left += cxButn + CXGAP + CXTEXTMARGIN+11; // left margin
	//		rcText.right -= cxButn;				 // right margin
	//		dc.SetBkMode(TRANSPARENT);			 // paint transparent text
	//		COLORREF colorText =m_pPopupMenu->m_itemPopup.textNormal;

	//		if (bDisabled) {
	//			DrawMenuText(dc, rcText + CPoint(1,1), pmd->text,
	//				m_pPopupMenu->m_itemPopup.textGrayed);
	//		}
	//		else if(bSelected)
	//		{
	//			DrawMenuText(dc, rcText + CPoint(1,1), pmd->text,
	//				m_pPopupMenu->m_itemPopup.textActive);
	//		}
	//		else
	//			DrawMenuText(dc, rcText, pmd->text, colorText); // finally!
	//	}
	//	dc.Detach();

	//	return TRUE; // handled
	//}
	//else
	//	return (BOOL)Default();
}
/******************************************
* 函数名 : OnMeasureItem
* 功能	 :  
*******************************************/
BOOL CSkinWnd::OnMeasureItem(LPMEASUREITEMSTRUCT lpms)
{
    return (BOOL)Default();
	//if(m_bHasMenu && (lpms->CtlType == ODT_MENU))
	//{
	//	ASSERT(lpms);
	//	CMyItemData* pmd = (CMyItemData*)lpms->itemData;
	//	ASSERT(pmd);
	//	if (lpms->CtlType != ODT_MENU || !pmd->IsMyItemData())
	//		return FALSE; // not handled by me

	//	if (pmd->fType & MFT_SEPARATOR) {
	//		// separator: use half system height and zero width
	//		lpms->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
	//		lpms->itemWidth  = 0;

	//	} else {
	//		CWindowDC dc(NULL);	// screen DC--I won't actually draw on it
	//		CRect rcText(0,0,0,0);
	//		dc.DrawText(pmd->text, rcText, DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT);
	//		lpms->itemHeight= max(GetSystemMetrics(SM_CYMENU), rcText.Height());
	//		int cx = rcText.Width()+20;	
	//		cx += CXTEXTMARGIN<<1;		
	//		cx += CXGAP;					
	//		cx -= GetSystemMetrics(SM_CXMENUCHECK)-1;
	//		lpms->itemWidth = cx+20;		// done deal
	//		lpms->itemHeight+=2;

	//	}
	//	return TRUE; // handled
	//}
	//else
	//	return (BOOL)Default();
}
/******************************************
* 函数名 : OnMeasureItem
* 功能	 :  
*******************************************/
void CSkinWnd::OnActivate(UINT nState, HWND hWnd, BOOL bMinimized)
{
	Default();
}
void CSkinWnd::OnTimter(UINT_PTR nIDEvent)
{
	Default();

	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();

	
	/*if(m_bHScroll)
		DrawHScrollBar(pDC);
	if(m_bVScroll)
		DrawVScrollBar(pDC);*/
}
void CSkinWnd::DrawHScrollBar(CDC *pDC)
{
	CRect rtWindow;
	GetWindowRect(&rtWindow);
	CRect rtPos;
	int nArrowSize;
	int nThumbSize;
	int nThumbPos;
	
	GetScrollRect(SB_HORZ,&rtPos,&nArrowSize,&nThumbSize,&nThumbPos);
	CMemDC memDC(pDC,rtPos);

	m_pSkinScrollBar->DrawHBackground(&memDC,rtPos);
	m_pSkinScrollBar->DrawHArrowLeft(&memDC,CRect(rtPos.left,rtPos.top,rtPos.left + nArrowSize,rtPos.bottom),m_nHArrowLeftState);
	m_pSkinScrollBar->DrawHArrowRight(&memDC,CRect(rtPos.right - nArrowSize,rtPos.top,rtPos.right,rtPos.bottom),m_nHArrowRightState);
	if(nThumbSize)
		m_pSkinScrollBar->DrawHThumb(&memDC,CRect(rtPos.left + nThumbPos,rtPos.top+1,rtPos.left +nThumbPos + nThumbSize,rtPos.bottom-1),m_nHThumbState);
}
void CSkinWnd::DrawVScrollBar(CDC *pDC)
{
	CRect rtWindow;
	GetWindowRect(&rtWindow);
	CRect rtPos;
	int nArrowSize;
	int nThumbSize;
	int nThumbPos;

	GetScrollRect(SB_VERT,&rtPos,&nArrowSize,&nThumbSize,&nThumbPos);
	CMemDC memDC(pDC,rtPos);
	m_pSkinScrollBar->DrawVBackground(&memDC,rtPos);
	m_pSkinScrollBar->DrawVArrowTop(&memDC,CRect(rtPos.left,rtPos.top,rtPos.right ,rtPos.top + nArrowSize),m_nVArrowTopState);
	m_pSkinScrollBar->DrawVArrowBottom(&memDC,CRect(rtPos.left,rtPos.bottom - nArrowSize,rtPos.right,rtPos.bottom),m_nVArrowBottomState);
	if(nThumbSize)
		m_pSkinScrollBar->DrawVThumb(&memDC,CRect(rtPos.left+1,rtPos.top +nThumbPos,rtPos.right -1,rtPos.top + +nThumbPos + nThumbSize),m_nVThumbState);
	
}
/******************************************
* 函数名 :  GetScrollRect
* 功能	 :  计算滚动条的区域等大小根据绘制坐标系统
*******************************************/
BOOL CSkinWnd::GetScrollRect(int nBar,LPRECT lpRect,int *nArrowSize,int *nThumbSize,int *nThumbPos)
{
	CRect rtClient,rtWindow;
	int pixels;
	BOOL vertical;
	GetClientRect(&rtClient);
	ClientToScreen(&rtClient);
	GetWindowRect(&rtWindow);

	switch(nBar)
	{
	case SB_HORZ:
		lpRect->left   = rtClient.left - rtWindow.left;
		lpRect->top    = rtClient.bottom - rtWindow.top;
		lpRect->right  = rtClient.right - rtWindow.left;
		lpRect->bottom = lpRect->top + GetSystemMetrics(SM_CYHSCROLL);

		vertical = FALSE;
		break;

	case SB_VERT:
		if((GetExStyle() & WS_EX_LEFTSCROLLBAR) != 0)
			lpRect->left   = rtClient.left - rtWindow.left - GetSystemMetrics(SM_CXVSCROLL);
		else
			lpRect->left   = rtClient.right - rtWindow.left;
		lpRect->top    = rtClient.top - rtWindow.top;
		lpRect->right  = lpRect->left + GetSystemMetrics(SM_CXVSCROLL);
		lpRect->bottom = rtClient.bottom - rtWindow.top;
		vertical = TRUE;
		break;

	case SB_CTL:
		GetClientRect(lpRect );
		vertical = ((GetStyle() & SBS_VERT) != 0);
		break;

	default:
		return FALSE;
	}


	if (vertical) 
		pixels = lpRect->bottom - lpRect->top;
	else 
		pixels = lpRect->right - lpRect->left;

	if (pixels <= 2*GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT)
	{
		if (pixels > SCROLL_MIN_RECT)
			*nArrowSize = (pixels - SCROLL_MIN_RECT) / 2;
		else
			*nArrowSize = 0;
		*nThumbPos = *nThumbSize = 0;
	}
	else
	{
		SCROLLINFO info ;
		
		::ZeroMemory((void*)&info,sizeof(info));
		info.cbSize = sizeof(SCROLLINFO);
		info.fMask = SIF_ALL;
		GetScrollInfo( m_hWnd, nBar, &info );

		if(info.nPos < info.nMin)
			info.nPos = info.nMin;
		if(info.nPos > info.nMax)
			info.nPos = info.nMax;

		
		*nArrowSize = GetSystemMetrics(SM_CXVSCROLL);
		pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));


		if (info.nPage)
		{
			*nThumbSize = MulDiv(pixels,info.nPage,(info.nMax - info.nMin+1));
			if (*nThumbSize < SCROLL_MIN_THUMB) 
				*nThumbSize = SCROLL_MIN_THUMB;
		}
		else 
			*nThumbSize = GetSystemMetrics(SM_CXVSCROLL);

		if(info.nPage >= (info.nMax -info.nMin + 1))
		{
			*nThumbPos = 0;
			*nThumbSize = 0;
			return vertical;
		}
		if ((pixels -= *nThumbSize ) < 0 )
		{
			/* Rectangle too small or scrollbar disabled -> no thumb */
			*nThumbPos = *nThumbSize = 0;
		}
		else
		{
			INT max = info.nMax - max( info.nPage-1, 0 );
			if (info.nMin >= max)
				*nThumbPos = *nArrowSize - SCROLL_ARROW_THUMB_OVERLAP;
			else
				*nThumbPos = *nArrowSize - SCROLL_ARROW_THUMB_OVERLAP
				+ MulDiv(pixels, (info.nPos-info.nMin),(max - info.nMin));
		}
	}
	return vertical;
}
SCROLL_HITTEST CSkinWnd::ScrollHitTest(int nBar,CPoint pt, BOOL bDragging )
{
	int arrowSize, thumbSize, thumbPos;
	CRect rect;

	BOOL vertical = GetScrollRect(nBar, &rect,
		&arrowSize, &thumbSize, &thumbPos );

	if ( !rect.PtInRect( pt ) ) 
		return SCROLL_NOWHERE;

	if (vertical)
	{
		if (pt.y < rect.top + arrowSize) 
			return SCROLL_TOP_ARROW;
		if (pt.y >= rect.bottom - arrowSize) 
			return SCROLL_BOTTOM_ARROW;
		if (!thumbPos) 
			return SCROLL_TOP_RECT;
		pt.y -= rect.top;
		if (pt.y < thumbPos)
			return SCROLL_TOP_RECT;
		if (pt.y >= thumbPos + thumbSize) 
			return SCROLL_BOTTOM_RECT;
	}
	else  /* horizontal */
	{
		if (pt.x < rect.left + arrowSize) 
			return SCROLL_TOP_ARROW;
		if (pt.x >= rect.right - arrowSize) 
			return SCROLL_BOTTOM_ARROW;
		if (!thumbPos) 
			return SCROLL_TOP_RECT;
		pt.x -= rect.left;
		if (pt.x < thumbPos) 
			return SCROLL_TOP_RECT;
		if (pt.x >= thumbPos + thumbSize) 
			return SCROLL_BOTTOM_RECT;
	}
	return SCROLL_THUMB;
}
BOOL CSkinWnd::IsScrollInfoActive(SCROLLINFO *si)
{
	if((si->nPage > (UINT)si->nMax
		|| si->nMax <= si->nMin || si->nMax == 0))
		return FALSE;
	else
		return TRUE;
}

// 获得该窗口是否有 Border 和 Scroll
DWORD CSkinWnd::GetBorderAndScroll(DWORD * dwExStyle)
{
#ifdef _WIN64
	LONG_PTR style = GetWindowLongPtr(m_hWnd, GWL_STYLE);
	LONG_PTR exstyle = GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
#else
	DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
	DWORD exstyle = GetWindowLong(m_hWnd, GWL_EXSTYLE);
#endif

	if(((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
		((exstyle) & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) )
		m_bBorder = TRUE;
	else
		m_bBorder = FALSE;

	m_bHScroll		= style & WS_HSCROLL;
	m_bVScroll		= style & WS_VSCROLL;
	m_bLeftScroll	= exstyle & WS_EX_LEFTSCROLLBAR;

	if(dwExStyle != NULL)
		*dwExStyle = exstyle;
	return style;

}

static TCHAR szPropStr[] = _T("SkinScrollBarPtr");
BOOL CSkinWnd::InitializeSB(HWND hwnd)
{
	SCROLLWND *sw;
	SCROLLINFO *si;
	RECT rect;
	LONG_PTR dwCurStyle;
	//BOOL fDisabled;

	::GetClientRect(hwnd, &rect);

	//if we have already initialized Cool Scrollbars for this window,
	//then stop the user from doing it again
	if(GetScrollWndFromHwnd(hwnd) != 0)
	{
		return FALSE;
	}

	//allocate a private scrollbar structure which we 
	//will use to keep track of the scrollbar data
	sw = (SCROLLWND *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SCROLLWND));

	si = &sw->sbarHorz.scrollInfo;
	si->cbSize = sizeof(SCROLLINFO);
	si->fMask  = SIF_ALL;
	GetScrollInfo(hwnd, SB_HORZ, si);

	si = &sw->sbarVert.scrollInfo;
	si->cbSize = sizeof(SCROLLINFO);
	si->fMask  = SIF_ALL;
	GetScrollInfo(hwnd, SB_VERT, si);

	//check to see if the window has left-aligned scrollbars
#ifdef _WIN64
	if(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR)
		sw->fLeftScrollbar = TRUE;
	else
		sw->fLeftScrollbar = FALSE;

	dwCurStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
#else
	if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR)
		sw->fLeftScrollbar = TRUE;
	else
		sw->fLeftScrollbar = FALSE;

	dwCurStyle = GetWindowLong(hwnd, GWL_STYLE);
#endif
	SetProp(hwnd, szPropStr, (HANDLE)sw);

	if(dwCurStyle & WS_HSCROLL)
		sw->sbarHorz.fScrollFlags = CSBS_VISIBLE;

	if(dwCurStyle & WS_VSCROLL)
		sw->sbarVert.fScrollFlags = CSBS_VISIBLE;

	//need to be able to distinguish between horizontal and vertical
	//scrollbars in some instances
	sw->sbarHorz.nBarType	     = SB_HORZ;
	sw->sbarVert.nBarType	     = SB_VERT;


	//set the default arrow sizes for the scrollbars
	sw->sbarHorz.nArrowLength	 = 0;
	sw->sbarHorz.nArrowWidth	 = 0;
	sw->sbarVert.nArrowLength	 = 0;
	sw->sbarVert.nArrowWidth	 = 0;

	sw->bPreventStyleChange		 = FALSE;


	return TRUE;
}
HRESULT CSkinWnd::UninitializeSB(HWND hwnd)
{
	int i = 0;
	SCROLLWND *sw = GetScrollWndFromHwnd(hwnd);
	if(!sw) return E_FAIL;

	//restore the window procedure with the original one
#ifdef _WIN64
	SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG)sw->oldproc);
#else
	SetWindowLong(hwnd, GWL_WNDPROC, (LONG)sw->oldproc);
#endif

	RemoveProp(hwnd, szPropStr);
	//SetWindowLong(hwnd, GWL_USERDATA, 0);

	//finally, release the memory needed for the cool scrollbars
	HeapFree(GetProcessHeap(), 0, sw);

	//Force WM_NCCALCSIZE and WM_NCPAINT so the original scrollbars can kick in
	//	RedrawNonClient(hwnd, TRUE);

	return S_OK;
}
/******************************************
* 函数名 :  GetScroolThumbVal
* 功能	 :  根据thumb的位置计算滚动条值
*******************************************/

UINT CSkinWnd::GetScroolThumbVal( SCROLLINFO *infoPtr, RECT *rect,
							   BOOL vertical, INT pos )
{
	INT thumbSize;
	INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;

	if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
		return infoPtr->nMin;

	if (infoPtr->nPage)
	{
		thumbSize = MulDiv(pixels,infoPtr->nPage,(infoPtr->nMax-infoPtr->nMin+1));
		if (thumbSize < SCROLL_MIN_THUMB)
			thumbSize = SCROLL_MIN_THUMB;
	}
	else 
		thumbSize = GetSystemMetrics(SM_CXVSCROLL);

	if ((pixels -= thumbSize) <= 0) 
		return infoPtr->nMin;

	pos = max( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) );
	if (pos > pixels) 
		pos = pixels;

	if (!infoPtr->nPage) 
		pos *= infoPtr->nMax - infoPtr->nMin;
	else 
		pos *= infoPtr->nMax - infoPtr->nMin - infoPtr->nPage + 1;
	return infoPtr->nMin + ((pos + pixels / 2) / pixels);
}
/***********************************************************************
*           HandleScrollEvent
*
* Handle a mouse or timer event for the scrollbar.
* 'pt' is the location of the mouse event in client (for SB_CTL) or
* windows coordinates.
*
************************************************************************/
void CSkinWnd::HandleScrollEvent( int nBar,UINT msg, const CPoint& pt1 )
{
	/* Previous mouse position for timer events */
	static POINT prevPt;
	/* Thumb position when tracking started. */
	static UINT trackThumbPos;
	/* Position in the scroll-bar of the last button-down event. */
	static INT lastClickPos;
	/* Position in the scroll-bar of the last mouse event. */
	static INT lastMousePos;
    CPoint pt = pt1;
	enum SCROLL_HITTEST hittest;
	HWND hwndOwner, hwndCtl;
	BOOL vertical;
	INT arrowSize, thumbSize, thumbPos;
	RECT rect;
	HDC hdc;

	SCROLLINFO info;
	info.cbSize = sizeof(info);
	info.fMask = SIF_ALL;
	GetScrollInfo( m_hWnd, nBar, &info);

	if ((m_nScrollHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN))
		return;
#ifdef _WIN64
	if (nBar == SB_CTL && (GetWindowLongPtr(m_hWnd, GWL_STYLE) & (SBS_SIZEGRIP | SBS_SIZEBOX)))
#else
	if (nBar == SB_CTL && (GetWindowLong( m_hWnd, GWL_STYLE ) & (SBS_SIZEGRIP | SBS_SIZEBOX)))
#endif
	{
		switch(msg)
		{
		case WM_LBUTTONDOWN:  /* Initialise mouse tracking */
			SetCapture( m_hWnd );
			prevPt = pt;
			m_nScrollHitTest  = hittest = SCROLL_THUMB;
			break;
		case WM_MOUSEMOVE:
			::GetClientRect(::GetParent(::GetParent(m_hWnd)),&rect);
			prevPt = pt;
			break;
		case WM_LBUTTONUP:
			ReleaseCapture();
			m_nScrollHitTest  = hittest = SCROLL_NOWHERE;
		//	if (m_hWnd==GetFocus()) ShowCaret(m_hWnd);
			break;
		case WM_TIMER:
			pt = prevPt;
			break;
		}
		return;
	}

	hdc = GetDCEx( m_hWnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
    CWnd* pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = CDC::FromHandle(hdc);
	vertical = GetScrollRect( nBar, &rect,&arrowSize, &thumbSize, &thumbPos );
	hwndOwner = (nBar == SB_CTL) ?:: GetParent(m_hWnd) : m_hWnd;
	hwndCtl   = (nBar == SB_CTL) ? m_hWnd : 0;

	switch(msg)
	{
	case WM_LBUTTONDOWN:  /* Initialise mouse tracking */
		m_bScrollVertical = vertical;
		m_nScrollHitTest  = hittest = ScrollHitTest(nBar, pt, FALSE );
		lastClickPos  = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
		lastMousePos  = lastClickPos;
		trackThumbPos = thumbPos;
		prevPt = pt;
	#ifdef _WIN64
		if (nBar == SB_CTL && (GetWindowLong(m_hWnd, GWL_STYLE) & WS_TABSTOP)) SetFocus(m_hWnd);
	#else
		if (nBar == SB_CTL && (GetWindowLong(m_hWnd, GWL_STYLE) & WS_TABSTOP)) SetFocus( m_hWnd );
	#endif
		SetCapture( m_hWnd );
		break;

	case WM_MOUSEMOVE:
		hittest = ScrollHitTest( nBar, pt, TRUE );
		prevPt = pt;
		break;

	case WM_LBUTTONUP:
		hittest = SCROLL_NOWHERE;
		ReleaseCapture();
		break;

	case WM_TIMER:
		pt = prevPt;
		hittest = ScrollHitTest(nBar, pt, FALSE );
		break;

	default:
		return;  /* Should never happen */
	}

	switch(m_nScrollHitTest)
	{
	case SCROLL_NOWHERE:  /* No tracking in progress */
		break;

	case SCROLL_TOP_ARROW:
		if (hittest == m_nScrollHitTest)
		{
			if(m_bScrollVertical)
			{
				m_nVArrowTopState = keScrollPressed;
				m_nVArrowBottomState = keScrollNormal;
				m_nVThumbState = keScrollNormal;
			//	DrawVScrollBar(pDC);
				m_pSkinScrollBar->DrawVArrowTop(pDC,CRect(rect.left,rect.top,rect.right,rect.top + arrowSize),m_nVArrowTopState);	
			}
			else
			{
				m_nHArrowLeftState = keScrollPressed;
				m_nHArrowRightState = keScrollNormal;
				m_nHThumbState = keScrollNormal;
			//	DrawHScrollBar(pDC);
				m_pSkinScrollBar->DrawHArrowLeft(pDC,CRect(rect.left,rect.top,rect.left + arrowSize,rect.bottom),m_nHArrowLeftState);
			}
			if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER))
			{
				::SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
					SB_LINEUP, (LPARAM)hwndCtl );
			}

			SetTimer( m_hWnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
									(TIMERPROC)0 );
		}
		else 
		{
			if(m_bScrollVertical)
				{
					m_nVArrowTopState = keScrollNormal;
				m_nVArrowBottomState = keScrollNormal;
				m_nVThumbState = keScrollNormal;
				DrawVScrollBar(pDC);	
			}
			else
			{
				m_nHArrowLeftState = keScrollNormal;
				m_nHArrowRightState = keScrollNormal;
				m_nHThumbState = keScrollNormal;
				DrawHScrollBar(pDC);				
			}
			KillTimer( m_hWnd, SCROLL_TIMER );
		}
		break;

	case SCROLL_TOP_RECT:
		if(m_bScrollVertical)
			DrawVScrollBar(pDC);
		else
			DrawHScrollBar(pDC);
		if (hittest == m_nScrollHitTest)
		{
			if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER))
			{
				SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
					SB_PAGEUP, (LPARAM)hwndCtl );
			}
			SetTimer( m_hWnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
								(TIMERPROC)0 );
		}
		else 
			KillTimer( m_hWnd, SCROLL_TIMER );
		break;

	case SCROLL_THUMB:
		if (msg == WM_LBUTTONDOWN)
		{
			if(m_pScrollWnd) 	
			{
				m_pScrollWnd->fThumbTracking = TRUE;
				if(vertical)
					m_pScrollWnd->sbarVert.scrollInfo.nTrackPos = m_pScrollWnd->sbarVert.scrollInfo.nPos;
				else
					m_pScrollWnd->sbarHorz.scrollInfo.nTrackPos = m_pScrollWnd->sbarHorz.scrollInfo.nPos;
			}

			m_hScrollTracking = m_hWnd;
			m_nTrackingBar = nBar;
			m_nTrackingPos = trackThumbPos + lastMousePos - lastClickPos;


			m_nTrackingVal = GetScroolThumbVal( &info, &rect,vertical,m_nTrackingPos );


			if(m_pScrollWnd)
			{
				if(vertical)
					m_pScrollWnd->sbarVert.scrollInfo.nTrackPos = m_nTrackingVal;
				else
					m_pScrollWnd->sbarHorz.scrollInfo.nTrackPos = m_nTrackingVal;
			}

			if(m_bScrollVertical)
			{
				m_nVArrowTopState = keScrollNormal;
				m_nVArrowBottomState = keScrollNormal;
				m_nVThumbState = keScrollPressed;
				DrawVScrollBar(pDC);	
			}
			else
			{
				m_nHArrowLeftState = keScrollNormal;
				m_nHArrowRightState = keScrollNormal;
				m_nHThumbState = keScrollPressed;
				DrawHScrollBar(pDC);				
			}

			if (!m_nTrackingBar)
				DrawMovingThumb(pDC, vertical,rect,  arrowSize, thumbSize);
		}
		else if (msg == WM_LBUTTONUP)
		{
			if(m_pScrollWnd) m_pScrollWnd->fThumbTracking = FALSE;
			if (m_nTrackingBar)
				DrawMovingThumb(pDC, vertical,rect,  arrowSize, thumbSize);
		}
		else  /* WM_MOUSEMOVE */
		{
			UINT pos;

			//if (!PtInRect( &rect, pt ))
			//{
			////	pos = lastClickPos;
			//}
			//else
			{
				pos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
			}
			if ( (pos != lastMousePos) || (!m_nTrackingBar) )
			{
				if (m_nTrackingBar)
					DrawMovingThumb( pDC,vertical, rect, arrowSize, thumbSize );
				lastMousePos = pos;
				m_nTrackingPos = trackThumbPos + pos - lastClickPos;

				m_nTrackingVal = GetScroolThumbVal( &info, &rect,
					vertical,
					m_nTrackingPos );
				if(m_pScrollWnd)
				{
					if(vertical)
						m_pScrollWnd->sbarVert.scrollInfo.nTrackPos = m_nTrackingVal;
					else
						m_pScrollWnd->sbarHorz.scrollInfo.nTrackPos = m_nTrackingVal;
				}
				
				SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
					MAKEWPARAM( SB_THUMBTRACK, m_nTrackingVal),
					(LPARAM)hwndCtl );

				if (!m_nTrackingBar)
					DrawMovingThumb( pDC,vertical, rect,arrowSize, thumbSize );
			}
			
		}
		break;

	case SCROLL_BOTTOM_RECT:
		if(m_bScrollVertical)
			DrawVScrollBar(pDC);
		else
			DrawHScrollBar(pDC);
		if (hittest == m_nScrollHitTest)
		{
			if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER))
			{
				SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
					SB_PAGEDOWN, (LPARAM)hwndCtl );
			}
			SetTimer( m_hWnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
					 (TIMERPROC)0 );
		}
		else 
			KillTimer( m_hWnd, SCROLL_TIMER );
		break;

	case SCROLL_BOTTOM_ARROW:
		if (hittest == m_nScrollHitTest)
		{
			if(m_bScrollVertical)
			{
				m_nVArrowTopState = keScrollPressed;
				m_nVArrowBottomState = keScrollNormal;
				m_nVThumbState = keScrollNormal;
				m_pSkinScrollBar->DrawVArrowBottom(pDC,CRect(rect.left,rect.bottom - arrowSize,rect.right,rect.bottom),m_nVArrowTopState);	
			}
			else
			{
				m_nHArrowLeftState = keScrollNormal;
				m_nHArrowRightState = keScrollPressed;
				m_nHThumbState = keScrollNormal;
				m_pSkinScrollBar->DrawHArrowRight(pDC,CRect(rect.right - arrowSize,rect.top,rect.right,rect.bottom),m_nHArrowLeftState);
			}

			if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER))
			{
				SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
					SB_LINEDOWN, (LPARAM)hwndCtl );
			}

			SetTimer( m_hWnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
					 (TIMERPROC)0 );
		}
		else 
		{
			if(m_bScrollVertical)
			{
				m_nVArrowTopState = keScrollNormal;
				m_nVArrowBottomState = keScrollNormal;
				m_nVThumbState = keScrollNormal;
				DrawVScrollBar(pDC);	
			}
			else
			{
				m_nHArrowLeftState = keScrollNormal;
				m_nHArrowRightState = keScrollNormal;
				m_nHThumbState = keScrollNormal;
				DrawHScrollBar(pDC);				
			}
			KillTimer( m_hWnd, SCROLL_TIMER );
		}
		break;
	}

	if (msg == WM_LBUTTONDOWN)
	{

		if (hittest == SCROLL_THUMB)
		{
			UINT val = GetScroolThumbVal( &info, &rect, vertical,
				trackThumbPos + lastMousePos - lastClickPos );
			SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
				MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)hwndCtl );
			
			if(m_bScrollVertical)
			{
				m_nVArrowTopState = keScrollNormal;
				m_nVArrowBottomState = keScrollNormal;
				m_nVThumbState = keScrollPressed;
				DrawVScrollBar(pDC);	
			}
			else
			{
				m_nHArrowLeftState = keScrollNormal;
				m_nHArrowRightState = keScrollNormal;
				m_nHThumbState = keScrollPressed;
				DrawHScrollBar(pDC);				
			}

		}
	}

	if (msg == WM_LBUTTONUP)
	{
		hittest =(SCROLL_HITTEST) m_nScrollHitTest;
		m_nScrollHitTest = SCROLL_NOWHERE;  /* Terminate tracking */

		if (hittest == SCROLL_THUMB)
		{
			UINT val = GetScroolThumbVal( &info, &rect, vertical,
				trackThumbPos + lastMousePos - lastClickPos );
			SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
				MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl );
		}
		SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
			SB_ENDSCROLL, (LPARAM)hwndCtl );

		/* Terminate tracking */
		m_hScrollTracking = NULL;
	}

	//ReleaseDC( m_hWnd, hdc );
}
void CSkinWnd::TrackScrollBar( int nBar, const CPoint& pt1 )
{
	MSG msg;
	INT xoffset = 0, yoffset = 0;
	CRect rtClient,rtWindow;
	GetClientRect(&rtClient);
	ClientToScreen(&rtClient);
	GetWindowRect(&rtWindow);
    POINT pt = pt1;
	if (nBar != SB_CTL)
	{
		xoffset = rtClient.left - rtWindow.left;
		yoffset = rtClient.top - rtWindow.top;
        
		::ScreenToClient(m_hWnd, &pt );
		pt.x += xoffset;
		pt.y += yoffset;
	}

	HandleScrollEvent(  nBar, WM_LBUTTONDOWN, pt );

	do
	{
		if (!GetMessage( &msg, 0, 0, 0 )) break;
		if (CallMsgFilter( &msg, MSGF_SCROLLBAR )) continue;
		if (msg.message == WM_LBUTTONUP ||
			msg.message == WM_MOUSEMOVE ||
			(msg.message == WM_TIMER && msg.wParam == SCROLL_TIMER))
		{
			pt.x = (short)LOWORD(msg.lParam) + xoffset;
			pt.y = (short)HIWORD(msg.lParam) + yoffset;
			HandleScrollEvent( nBar, msg.message, pt );
		}
		else
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		if (!IsWindow( m_hWnd ))
		{
			ReleaseCapture();
			break;
		}
	} while (msg.message != WM_LBUTTONUP);
}

void CSkinWnd::DrawMovingThumb(CDC *pDC,BOOL bVertical,CRect rtPos,int nArrowSize,int nThumbSize)
{
	int pos = m_nTrackingPos;
	int max_size;

	if( bVertical )
		max_size = rtPos.bottom - rtPos.top;
	else
		max_size = rtPos.right - rtPos.left;

	max_size -= (nArrowSize-SCROLL_ARROW_THUMB_OVERLAP) + nThumbSize;

	if( pos < (nArrowSize-SCROLL_ARROW_THUMB_OVERLAP) )
		pos = (nArrowSize-SCROLL_ARROW_THUMB_OVERLAP);
	else if( pos > max_size )
		pos = max_size;

	CMemDC memDC(pDC,rtPos);
	if(!bVertical)
	{
		m_pSkinScrollBar->DrawHBackground(&memDC,rtPos);
		m_pSkinScrollBar->DrawHArrowLeft(&memDC,CRect(rtPos.left,rtPos.top,rtPos.left + nArrowSize,rtPos.bottom),m_nHArrowLeftState);
		m_pSkinScrollBar->DrawHArrowRight(&memDC,CRect(rtPos.right - nArrowSize,rtPos.top,rtPos.right,rtPos.bottom),m_nHArrowRightState);
		m_pSkinScrollBar->DrawHThumb(&memDC,CRect(rtPos.left + pos,rtPos.top+1,rtPos.left +pos + nThumbSize,rtPos.bottom-1),m_nHThumbState);
	}
	else
	{
		m_pSkinScrollBar->DrawVBackground(&memDC,rtPos);
		m_pSkinScrollBar->DrawVArrowTop(&memDC,CRect(rtPos.left,rtPos.top,rtPos.right,rtPos.top + nArrowSize),m_nVArrowTopState);
		m_pSkinScrollBar->DrawVArrowBottom(&memDC,CRect(rtPos.left,rtPos.bottom  - nArrowSize,rtPos.right,rtPos.bottom),m_nVArrowBottomState);
		m_pSkinScrollBar->DrawVThumb(&memDC,CRect(rtPos.left+1,rtPos.top + pos,rtPos.right-1 ,rtPos.top +pos + nThumbSize),m_nVThumbState);
	}
	

	m_nTrackingBar = !m_nTrackingBar;
}


void CSkinWnd::DrawSeparator(CRect& rc, CDC& dc)
{
	if(!m_pPopupMenu->DrawImageSection(&dc,rc,m_pPopupMenu->m_itemPopup.imageActive))
	{
		CBrush brush;
		brush.CreateSolidBrush(m_pPopupMenu->m_colorBackground);
		dc.FillRect(rc,&brush);
		
	}
	rc.top += rc.Height() >> 1;
	rc.bottom = rc.top + 1;
	rc.left += 5;
	rc.right -= 5;
	if(!m_pPopupMenu->DrawImageSection(&dc,rc,m_pPopupMenu->m_itemPopup.imageSeparator))
	{
		
		dc.DrawEdge(rc, EDGE_ETCHED, BF_TOP);	
	}
}		


void CSkinWnd::DrawMenuText( CDC& dc, const CRect& rc1, const CString& text, COLORREF color )
{
    CRect rc = rc1;
	CString left = text;
	CString right;
	int iTabPos = left.Find(_T('\t'));
	if (iTabPos >= 0) {
		right = left.Right(left.GetLength() - iTabPos - 1);
		left  = left.Left(iTabPos);
	}
	dc.SetTextColor(color);
	dc.DrawText(left, &rc, DT_SINGLELINE|DT_LEFT|DT_VCENTER);
	if (iTabPos > 0)
		dc.DrawText(right, &rc, DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_RIGHT);
}


void CSkinWnd::PLSelectRect(CDC& dc, const CRect& rc)
{
	if(!m_pPopupMenu->DrawImageSection(&dc,rc,m_pPopupMenu->m_itemPopup.imageActive))
	{
		CBrush brush;
		brush.CreateSolidBrush(m_pPopupMenu->m_itemPopup.colorActive);
		dc.FillRect(rc,&brush);
		brush.DeleteObject( );
	}
}

void CSkinWnd::PLNormalRect(CDC& dc, const CRect& rc)
{
	if(!m_pPopupMenu->DrawImageSection(&dc,rc,m_pPopupMenu->m_itemPopup.imageActive))
	{
		CBrush brush;
		brush.CreateSolidBrush(m_pPopupMenu->m_colorBackground);
		dc.FillRect(rc,&brush);
		brush.DeleteObject( );
	}
}


void CSkinWnd::ConvertMenu(CMenu* pMenu,
							UINT nIndex, BOOL bSysMenu, BOOL bShowButtons)
{
	ASSERT_VALID(pMenu);

	CString sItemName;

	UINT nItem = pMenu->GetMenuItemCount();
	for (UINT i = 0; i < nItem; i++) 
	{	
		// loop over each item in menu
		// get menu item info
		TCHAR itemname[256] = {0};
		CMenuItemInfo info;
		info.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_ID
			| MIIM_TYPE;
		info.dwTypeData = itemname;
		info.cch = sizeof(itemname);
		::GetMenuItemInfo(*pMenu, i, TRUE, (MENUITEMINFO *)&info);
		CMyItemData* pmd = (CMyItemData*)(info.dwItemData);


		if (pmd && !pmd->IsMyItemData()) 
			continue; 
		// owner-draw menu item isn't mine--leave it alone

        // lynnux 2010.1.12
        // 系统菜单确实有点不好处理，下面的处理可以达到目前想要的效果，以后有问题再改
		//// Koji MATSUNAMI 1999.2.23
		//if (bSysMenu && info.wID >= 0xF000) {
		//	continue; // don't do for system menu commands
		//}

		// now that I have the info, I will modify it
		info.fMask = 0;	// assume nothing to change


		if (bShowButtons) 
		{
			if (!(info.fType & MFT_OWNERDRAW)) 
			{
				info.fType |= MFT_OWNERDRAW;
				info.fMask |= MIIM_TYPE;
				if (!pmd) 
				{									// if no item data:
					pmd = new CMyItemData;				//   create one
					ASSERT(pmd);							//   (I hope)
					pmd->fType = info.fType;			//   handy when drawing
					info.dwItemData = (DWORD)pmd;		//   set in menu item data
					info.fMask |= MIIM_DATA;			//   set item data
				}
				pmd->text = info.dwTypeData;			// copy menu item string
			}

			// now add the menu to list of "converted" menus
			HMENU hmenu = pMenu->GetSafeHmenu();
			ASSERT(hmenu);
			if (!m_menuList.Find(hmenu))
				m_menuList.AddHead(hmenu);

            // if after all the above, there is anything to change, change it
            if (info.fMask) {
                SetMenuItemInfo(*pMenu, i, TRUE, (MENUITEMINFO *)&info);
            }
		} 
		else 
		{
            BOOL bMoreJob = FALSE;  // 是否需要再对MFT_BITMAP进行处理
			// no buttons -- I'm converting to strings
			if (info.fType & MFT_OWNERDRAW) 
			{	
				info.fType &= ~MFT_OWNERDRAW;		//   turn it off
				info.fMask |= MIIM_TYPE;			//   change item type
                // 有了MIIM_TYPE属性，如果有MFT_BITMAP需要进一步处理
                if (info.fType & MFT_BITMAP)       
                {
                    bMoreJob = TRUE;
                    // 需要去掉MFT_BITMAP，用MIIM_BITMAP去设置hbmpItem
                    info.fType &= ~MFT_BITMAP; 
                }
				ASSERT(pmd);							//   sanity check
				sItemName = pmd->text;				//   save name before deleting pmd
			} 
			else										// otherwise:
				sItemName = info.dwTypeData;		//   use name from MENUITEMINFO_LOCAL

			if (pmd)
			{
				info.dwItemData = NULL;				// item data is NULL
				info.fMask |= MIIM_DATA;			// change it
				safe_delete(pmd);								// and item data too
			}


			if (info.fMask & MIIM_TYPE) 
			{
				// if setting name, copy name from CString to buffer and set cch
				_tcsncpy(itemname, sItemName, sizeof(itemname));
				info.dwTypeData = itemname;
				info.cch = sItemName.GetLength();
			}
            
            // 如果再添加MIIM_BITMAP标志，那里下面的调用会失败，所以分两步，具体参见MSDN的MENUITEMINFO
            // if after all the above, there is anything to change, change it
            if (info.fMask) {
                SetMenuItemInfo(*pMenu, i, TRUE, (MENUITEMINFO *)&info);
            }

            // MIIM_BITMAP不能跟它们一起处理
            if (bMoreJob)
            {
#ifndef MIIM_BITMAP
#define MIIM_BITMAP      0x00000080
#endif
                info.fMask = MIIM_BITMAP;
                SetMenuItemInfo(*pMenu, i, TRUE, (MENUITEMINFO *)&info);
            }
		}



	}
}

//////////////////////////////////////////////////////////////////////
//  data   :    2009/11/19 22:28
//  file   :    SkinWnd.cpp
//  author :    lynnux
//  site   :    www.lynnmh.com
//  contact:    lynnux@yeah.net
//  note   :    implement of CAutoReleaseDC
//////////////////////////////////////////////////////////////////////
CAutoReleaseDC::CAutoReleaseDC( CWnd* pthis )
: m_handle(0)
, m_cwnd(pthis)
{
}

CAutoReleaseDC::~CAutoReleaseDC()
{
    if (m_cwnd && m_handle)
    {
        m_cwnd->ReleaseDC(m_handle);
    }
}

// some place get the dc more than once, so we should release the Previous dc handle
CAutoReleaseDC& CAutoReleaseDC::operator=( CDC* p )
{
    if (m_cwnd 
        && m_handle
        && (m_handle!= p)
        )
    {
        m_cwnd->ReleaseDC(m_handle);
    }
    m_handle = p;
    return *this;
}

CAutoReleaseDC::operator CDC*()
{
    return m_handle;
}

CDC* CAutoReleaseDC::operator->()
{
    return m_handle;
}